package com.lizk.net.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class Server {
	
	//定义服务器端的通道
	ServerSocketChannel ssc = null;
	//定义selector
	Selector selector = null;
	
	
	Server() throws IOException{
		//打开通道
		ssc = ServerSocketChannel.open();
		//设置为非阻塞的模式运行
		ssc.configureBlocking(false);
		//打开selector
		selector = Selector.open();
		//绑定监听的端口
		ssc.bind(new InetSocketAddress("127.0.0.1",10001));
		//注册到selector上，监听accept事件
		ssc.register(selector, SelectionKey.OP_ACCEPT);
	}
	public static void main(String[] args) throws IOException {
		Server server = new Server();
		server.start();
	}
	
	public void start() throws IOException{
		
		//开始轮循
		while(true){
			
			//对所有的通道做一次检查
			int readyChannels = selector.select();

			//如果没有通道那么直接下一次循环
			if(readyChannels <= 0 ){
				continue;
			}
			
			//得到轮循后需要处理的通道的key集合
			Set<SelectionKey> keySet = selector.selectedKeys();
			
			//获取迭代替
			Iterator<SelectionKey> it =  keySet.iterator();
			
			while (it.hasNext()){
				//得到当前需要处理的key
				SelectionKey key = it.next();
				//判断通道的状态，根据不同的状态做处理
				if(key.isAcceptable()){
					try {
						accept(key);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}else if(key.isValid() && key.isReadable()){
					try {
						read(key);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//把处理过的通道移除
				it.remove();
			}
			
			//为了测试方便，增加睡眠时间
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public  void accept(SelectionKey key) throws IOException{
		//通过key获取到通道
		ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
		//开启监听，这里是阻塞的
		SocketChannel sc = ssc.accept();
		System.out.println("接收消息");
		//新的通道设置为非阻塞的模式
		sc.configureBlocking(false);
		//新通道注册到selector上，监听读操作
		sc.register(selector, SelectionKey.OP_READ);
	}
	
	public void read(SelectionKey key) throws IOException{
		//读取数据
		SocketChannel channel =  (SocketChannel)key.channel();
		ByteBuffer bb = ByteBuffer.allocate(1024);
		bb.clear();
		int result = channel.read(bb);
		//当没有读到数据的时候把通道关闭（如果不关闭会一直从通道读数据）
		if(result <= -1 ){
			channel.close();
		}else{
			bb.flip();
			//byte[] b = new byte[bb.remaining()];
			//bb.get(b);
			byte[] b = bb.array();
			System.out.println(new String (b));
		}
		
	}
	
}
